package org.example.websocket;

import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Author：无敌暴龙战士
 * @Package：org.example.websocket
 * @Project：learn_websocket
 * @name：WebSocketServer
 * @Date：2025/1/13 12:43
 * @Filename：WebSocketServer
 * @Description:
 */
@Component
@ServerEndpoint("/ws/{clientId}")
public class WebSocketServer {
    private static Map<String, Session> sessions = new HashMap<>();

    /**
     * onOpen 方法在新的 WebSocket 连接建立时调用，将新会话添加到 sessions 映射中。
     *
     * @param session
     * @param clientId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("clientId") String clientId) throws JsonProcessingException {
        System.out.println("客户端= " + clientId + "建立连接");
        sessions.put(clientId, session);

        updateList();
    }

    private void updateList() throws JsonProcessingException {
        Set<String> clientIds = sessions.keySet();
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(clientIds);

        sendToAll("list-" + json);
    }

    /**
     * onMessage 方法在收到客户端消息时调用，打印消息内容。
     *
     * @param msg
     * @param clientId
     */
    @OnMessage
    public void onMessage(String msg, @PathParam("clientId") String clientId) {
        System.out.println("收到客户端= " + clientId + "的消息" + msg);
        if (msg.contains("::")) {
            String to = msg.split("::")[0];
            msg = msg.split("::")[1];
            msg = clientId + ":<br/>" + msg;
            this.sendToOne(to, msg);
        } else {
            msg = clientId + ":<br/>" + msg;
            this.sendToAll(msg);
        }
    }

    /**
     * onClose 方法在 WebSocket 连接关闭时调用，从 sessions 映射中移除会话。
     *
     * @param clientId
     */
    @OnClose
    public void onClose(@PathParam("clientId") String clientId) {
        System.out.println("客户端= " + clientId + "断开连接");
        sessions.remove(clientId);
    }

    /**
     * sendToAll 方法将消息发送给所有连接的客户端。
     *
     * @param msg
     */
    public void sendToAll(String msg) {
        sessions.forEach((clientId, session) -> {
            try {
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * sendToOne 方法将消息发送给特定的客户端。
     *
     * @param to
     * @param msg
     */
    public void sendToOne(String to, String msg) {
        try {
            sessions.get(to).getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
